前兩天,我整理了分錢系統的操作流程與資料結構。今天回到最基本的功能:一筆支出,究竟要怎麼變成每個人的分攤金額,以及最後的付款清單?
平均分攤在原型裡已經存在,所以今天不需要重新做一次。我請 AI 協助檢查現有程式,並執行具體案例,確認目前的計算符合預期。今天的重點,是理解與驗證已經有的功能,而不是繼續堆疊新功能。
檢查程式後,可以看到計算主要集中在 logic.js。裡面的 allocate 負責算出一筆支出由哪些人分攤、每人負擔多少;settle 則整理每個人的已付款與應分攤金額,再產生付款清單。這兩個步驟看起來相近,但其實回答的是不同問題。
分攤回答的是「這筆消費每個人應該負擔多少」,結算回答的是「考慮已經付出去的錢,現在還需要付給誰多少」。如果把兩件事混在一起,就容易把先付款的人也算成需要再付款,或把他應該收回的金額算錯。
今天先使用最容易手動核對的案例:小明、小美和阿哲一起吃飯,總共花了 1,200 元,由小明先付款,三個人平均分攤。每個人的負擔都是 400 元,但小明已經先付了全部的 1,200 元,所以他應該收回 800 元。最後的付款清單,就是小美付小明 400 元,阿哲付小明 400 元。
這個案例除了檢查每人是否分到 400 元,也檢查了所有人的分攤加總是否等於 1,200 元,以及應收與應付的淨額加總是否為零。這些條件能幫助確認,系統沒有憑空多算或少算一筆錢。
接著,我們把付款人改成小美,其他條件保持相同。三個人吃的是同一頓飯,所以每人的分攤仍然是 400 元;改變的只有誰先付款,以及最後誰應該收錢。驗證結果顯示,小明與阿哲各付小美 400 元,符合預期。
這讓我更清楚地理解,付款人不是「不用分攤的人」,而是「已經先拿出錢的人」。系統必須同時記得他應該負擔多少,以及他已經付了多少,才能正確算出差額。
另一個需要確認的地方,是平均分攤的人數應該從哪裡來。帳本裡有三個人,不代表每一筆支出都要除以三。如果只有小明和小美參與一筆 1,200 元的消費,那麼兩人應該各負擔 600 元,阿哲不需要分攤。這個案例也通過驗證,確認程式使用的是該筆支出的參與名單,而不是直接使用帳本總人數。
我們也檢查了代墊者沒有參與消費的情況。假設小明只是幫小美和阿哲先付 1,200 元,自己沒有消費,那麼小明的應分攤金額應該是零,小美與阿哲各負擔 600 元,最後各付小明 600 元。這個結果再次確認,付款人與分攤成員可以是不同的角色。
接著是修改金額後的重新計算。同一筆三人平均分攤的支出,從 1,200 元改成 1,500 元,再呼叫計算函式,每人的結果應該更新成 500 元。這次驗證確認了計算模組能根據修改後的資料產生新結果,而不是沿用原本的 400 元。
不過,這裡也要分清楚測試範圍。今天是直接對計算模組執行驗證,並沒有重新在瀏覽器裡操作修改表單。因此,可以確認修改後的資料重新送入計算函式時,結果正確,但不能只靠這項測試,就宣稱整個畫面的編輯流程也已經完整驗證。
除了正常案例,今天也測試了三種不應接受的輸入:沒有任何分攤成員、支出金額為零,以及付款人不在成員名單裡。這三種情況都被程式拒絕,沒有繼續產生結算結果。
錯誤資料不能只是算出一個看似合理的答案。沒有參與者時,平均分攤本身就沒有意義;付款人不存在時,也無法正確連接代墊紀錄。先擋住這些情況,是讓後續結果可信的一部分。
今天總共執行了八項驗證,全部通過。這代表目前選定的單筆平均分攤案例符合預期,但不代表整個系統已經沒有錯誤。現金找零、資料保存、完整的畫面操作,以及更多邊界情況,都還需要各自的驗證。
檢查程式時,也發現現有原型與第六天的設計之間,仍然有需要銜接的地方。昨天規劃用固定的成員 ID 連接資料,但目前程式仍然使用姓名識別付款人與參與者。這項設計還沒有實作進去,所以不能因為文件裡已經寫好,就當成程式也已完成。
現階段先保留這個差異,之後調整資料結構時,再一併處理成員、支出和畫面的連接方式。今天不為了完成平均分攤的驗證,同時擴大成整個資料結構的改寫,讓每次工作的範圍保持清楚。
這次也讓我體會到,和 AI 合作不只有請它寫程式。還可以請它協助閱讀現有邏輯,把需求轉成具體案例,再用程式檢查結果。重點是每個案例都要有事先想清楚的答案,而不是程式算出什麼,就接受什麼。
今天沒有新增產品功能,也沒有發布新版,但完成了單筆平均分攤的邏輯檢查與八項驗證。對我來說,這是把「看起來可以用」往前推進到「在這些明確情境下,已經確認算得對」。
目前使用的主要案例都能整除,但真實生活中的金額不一定這麼剛好。接下來會進一步處理 100 元分給三個人這類情況,確認剩下的一元怎麼分,以及成員順序會不會影響結果。Day 8,就從零頭分配與金額加總的驗證開始。